namespace BM.Tools.WebControls.MForm.Controls.Helper
{
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.Web.UI;    

    /// <summary>
    /// The class provides search methods for the control or the control collection to find parent or children of certain type
    /// </summary>
    public static class ControlSeeker
    {
        /// <summary>
        /// finds the first child of the given type
        /// </summary>
        /// <param name="cc">
        /// The control collection
        /// </param>
        /// <param name="recursively">
        /// should run recursively.
        /// </param>
        /// <typeparam name="T">
        /// the type of the control to search
        /// </typeparam>
        /// <returns>
        /// either null or the control that it found
        /// </returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This method is similar to the OfType Linq method and its usage should not be complicated at all")]
        public static T FirstOfType<T>(this ControlCollection cc, bool recursively) where T : class
        {
            foreach (Control c in cc)
            {
                T asT = c as T;
                if (asT != null)
                {
                    return asT;
                }
            }

            if (recursively)
            {
                foreach (Control c in cc)
                {
                    T output = FirstOfType<T>(c.Controls, true);
                    if (output != null)
                    {
                        return output;
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// finds children of the given type        
        /// </summary>
        /// <param name="cc">
        /// The control collection.
        /// </param>
        /// <param name="recursively">
        /// should run recursively.
        /// </param>
        /// <typeparam name="T">
        /// the type of the control to search
        /// </typeparam>
        /// <returns>
        /// the enumeration of controls
        /// </returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This method is similar to the OfType Linq method and its usage should not be complicated at all")]
        public static IEnumerable<T> OfType<T>(this ControlCollection cc, bool recursively) where T : class
        {
            foreach (Control c in cc)
            {
                T asT = c as T;
                if (asT != null)
                {
                    yield return asT;
                }
                else if (recursively)
                {
                    foreach (var child in OfType<T>(c.Controls, true))
                    {
                        yield return child;
                    }
                }
            }
        }

        /// <summary>
        /// finds for the ancestor of the given type
        /// </summary>
        /// <param name="control">
        /// The control.
        /// </param>
        /// <typeparam name="T">
        /// the type of the control to search
        /// </typeparam>
        /// <returns>
        /// either null or the control that it found
        /// </returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "This method is similar to the OfType Linq method and its usage should not be complicated at all")]
        public static T ParentOfType<T>(this Control control) where T : class
        {
            if (control == null)
            {
                return null;
            }

            T parent = control.Parent as T;
            if (parent != null)
            {
                return parent;
            }

            return control.Parent.ParentOfType<T>();
        }
    }
}